#!/usr/bin/python 
# @Time  : 2020/9/17 16:13
# @Author: LOUIE
# @Desc  : HTTP响应处理
from utils.logger import log
from utils import tools
import json


class HttpResponse(object):

    def __init__(self, response=None):
        self.response = response
        self.response_meta = {
            "status_code": self.status_code,
            "headers": self.headers,
            "cookies": self.cookies,
            "content": self.content,
        }

    def __getattr__(self, key):
        if key in ["json", "content", "body"]:
            try:
                value = self.response.json()
            except ValueError:
                value = self.response.content
        elif key == "cookies":
            value = self.response.cookies.get_dict()
        else:
            try:
                value = getattr(self.response, key)
            except AttributeError:
                error_msg = "response object does not have attribute: {}".format(key)
                log.error(error_msg)
                raise Exception(error_msg)

        self.__dict__[key] = value
        return value

    def _search_jsonpath(self, expr):
        try:
            check_value = tools.get_target_value(self.response_meta, expr)
        except ValueError as ex:
            log.error(
                f"failed to search with jsonpath.\n"
                f"data: {self.response_meta}\n"
                f"exception: {ex}"
            )
            raise

        return check_value

    def extract_value(self, extractors):

        log.info("start to extract from response object.")

        if not extractors:
            return

        extract_mapping = {}
        for key, field in extractors.items():
            field_value = self._search_jsonpath(field)
            extract_mapping[key] = field_value

        log.info(f"extract mapping:\n{json.dumps(extract_mapping, indent=4, ensure_ascii=False)}\n")

        return extract_mapping

    def validate(self, validators):

        if validators is None:
            return

        if not isinstance(validators, list):
            return "validator must be list type"

        log.info("start to validate result.")

        for validator in validators:

            for comparator, expected in validator.items():

                try:

                    if comparator in ['equal', 'eq', 'Equal']:
                        actual = tools.get_target_value(self.response_meta, expected[0])
                        assert expected[1] == actual

                    elif comparator in ['not_equal', 'not_eq', 'notEqual']:
                        actual = tools.get_target_value(self.response_meta, expected[0])
                        assert expected[1] != actual

                    elif comparator in ['in', 'In']:
                        assert expected[0] in str(self.response_meta)

                    elif comparator in ['not_in', 'notIn']:
                        assert expected[0] not in str(self.response_meta)

                    log.info(f"assert result: 【 Passed 】\n"
                             f"comparator: {comparator}\n"
                             f"expected: {expected[-1]}\n"
                             )
                except AssertionError as ex:
                    log.error(f"assert result: 【 Failed 】\n"
                              f"comparator: {comparator}\n"
                              f"expected: {expected[-1]}\n"
                              f"actual: {actual}"
                              )
                    raise ex
